本文使用的测试环境是arm64架构真机
为了探究Tagged Pointer本质,可以查看runtime源码,主要看文件objc-internal.h
。
宏定义
可以看到以下宏定义,只有在64位系统才支持Tagged Pointer
。
1 |
64-bit的mac,tag存储在LSB(Least Significant Bit 最低位)。其它情况比如64位的真机和模拟器,tag存储在MSB(Most Significant Bit 最高位)。
1 |
|
接下来是一个枚举定义,定义了默认的使用Tagged Pointer
的类。例如NSString、NSNumber、NSIndexPath、NSDate(OBJC_TAG_NSAtom、OBJC_TAG_1、OBJC_TAG_NSManagedObjectID不知道是啥意思,还请知道的同学告诉我)。
1 | enum objc_tag_index_t : uint16_t |
方法定义
判断是不是Tagged Pointer
1 | static inline bool |
生成一个Tagged Pointer
,最高的4位是tagged,剩下的是数据
1 | static inline void * _Nonnull |
从Tagged Pointer
中取出值
1 | static inline uintptr_t |
NSNumber应用举例
可以使用下面代码来验证NSNumber如何使用Tagged Pointer
1 | NSNumber *charNumber = [NSNumber numberWithChar:'1']; |
不难发现规律,都是以b(1011)开头
- 最高位是1,说明这个指针是一个
Tagged Pointer
- 第61-63位是11(十进制是3),也就是
OBJC_TAG_NSNumber
(查上面的枚举) - 第1-4位是NSNumber的类型:比如,char是0、short是1、int是2、float是4
- 剩下的56位就是真正的值了
NSString应用举例
1 | NSString *str1 = [NSString stringWithFormat:@"a"]; |
与NSNumber类似
- 最高位是1,说明这个指针是一个
Tagged Pointer
- 第61-63位是11(十进制是2),也就是
OBJC_TAG_NSString
- 第1-4位是字符串长度
- 剩下的56位就是真正的值了
更多细节推荐这篇文章采用Tagged Pointer的字符串
参考文章